/*
 * Copyright 2012-2021 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.boot.autoconfigure.r2dbc;

import java.time.Duration;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;

import io.r2dbc.spi.ValidationDepth;

import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * R2DBC的配置属性。
 *
 * @author Mark Paluch
 * @author Andreas Killaitis
 * @author Stephane Nicoll
 * @author Rodolpho S. Couto
 * @since 2.3.0
 */
@ConfigurationProperties(prefix = "spring.r2dbc")
public class R2dbcProperties {

	/**
	 * 数据库名称。如果URL中未指定名称则设置此项。使用嵌入式数据库时
	 * 默认为"testdb"。
	 */
	private String name;

	/**
	 * 是否生成随机数据库名称。启用时将忽略任何已配置的名称。
	 */
	private boolean generateUniqueName;

	/**
	 * 数据库的R2DBC URL。URL中指定的数据库名称、用户名、密码和连接池选项
	 * 优先于单独的选项。
	 */
	private String url;

	/**
	 * 数据库的登录用户名。如果URL中未指定用户名则设置此项。
	 */
	private String username;

	/**
	 * 数据库的登录密码。如果URL中未指定密码则设置此项。
	 */
	private String password;

	/**
	 * 附加的R2DBC选项。
	 */
	private final Map<String, String> properties = new LinkedHashMap<>();

	private final Pool pool = new Pool();

	private String uniqueName;

	public String getName() {
		return this.name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public boolean isGenerateUniqueName() {
		return this.generateUniqueName;
	}

	public void setGenerateUniqueName(boolean generateUniqueName) {
		this.generateUniqueName = generateUniqueName;
	}

	public String getUrl() {
		return this.url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public String getUsername() {
		return this.username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return this.password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public Map<String, String> getProperties() {
		return this.properties;
	}

	public Pool getPool() {
		return this.pool;
	}

	/**
	 * 提供此实例特有的唯一名称。多次调用此方法将返回相同的唯一名称。
	 * @return 此实例的唯一名称
	 */
	public String determineUniqueName() {
		if (this.uniqueName == null) {
			this.uniqueName = UUID.randomUUID().toString();
		}
		return this.uniqueName;
	}

	public static class Pool {

		/**
		 * 连接在池中允许保持空闲状态的最大时长。
		 */
		private Duration maxIdleTime = Duration.ofMinutes(30);

		/**
		 * 连接在池中的最大生命周期。默认情况下，连接具有无限的生命周期。
		 */
		private Duration maxLifeTime;

		/**
		 * 从池中获取连接的最大时间。默认情况下，无限期等待。
		 */
		private Duration maxAcquireTime;

		/**
		 * 等待创建新连接的最大时间。默认情况下，无限期等待。
		 */
		private Duration maxCreateConnectionTime;

		/**
		 * 初始连接池大小。
		 */
		private int initialSize = 10;

		/**
		 * 最大连接池大小。
		 */
		private int maxSize = 10;

		/**
		 * 验证查询。
		 */
		private String validationQuery;

		/**
		 * 验证深度。
		 */
		private ValidationDepth validationDepth = ValidationDepth.LOCAL;

		/**
		 * 是否启用连接池。需要r2dbc-pool。
		 */
		private boolean enabled = true;

		public Duration getMaxIdleTime() {
			return this.maxIdleTime;
		}

		public void setMaxIdleTime(Duration maxIdleTime) {
			this.maxIdleTime = maxIdleTime;
		}

		public Duration getMaxLifeTime() {
			return this.maxLifeTime;
		}

		public void setMaxLifeTime(Duration maxLifeTime) {
			this.maxLifeTime = maxLifeTime;
		}

		public Duration getMaxAcquireTime() {
			return this.maxAcquireTime;
		}

		public void setMaxAcquireTime(Duration maxAcquireTime) {
			this.maxAcquireTime = maxAcquireTime;
		}

		public Duration getMaxCreateConnectionTime() {
			return this.maxCreateConnectionTime;
		}

		public void setMaxCreateConnectionTime(Duration maxCreateConnectionTime) {
			this.maxCreateConnectionTime = maxCreateConnectionTime;
		}

		public int getInitialSize() {
			return this.initialSize;
		}

		public void setInitialSize(int initialSize) {
			this.initialSize = initialSize;
		}

		public int getMaxSize() {
			return this.maxSize;
		}

		public void setMaxSize(int maxSize) {
			this.maxSize = maxSize;
		}

		public String getValidationQuery() {
			return this.validationQuery;
		}

		public void setValidationQuery(String validationQuery) {
			this.validationQuery = validationQuery;
		}

		public ValidationDepth getValidationDepth() {
			return this.validationDepth;
		}

		public void setValidationDepth(ValidationDepth validationDepth) {
			this.validationDepth = validationDepth;
		}

		public boolean isEnabled() {
			return this.enabled;
		}

		public void setEnabled(boolean enabled) {
			this.enabled = enabled;
		}

	}

}
